package com.atguigu.day3;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *写线程首先获取写锁，更新数据，然后将锁降级为读锁。读线程在获取读锁后读取数据。
 *该过程演示了锁降级的概念，允许多个线程在持有读锁的情况下同时访问数据，提高并发性能。
 *⚠️在锁降级期间，我们要确保数据的一致性，即在降级为读锁之前和之后都可以正确读取数据。
 * 这是锁降级的关键部分，即：在获取读锁，再释放写锁
 */
public class LockDowngradingDemo {
    //创建一个读写锁对象
    private ReadWriteLock rwLock = new ReentrantReadWriteLock();
    //拆分读写锁
    private Lock readLock = rwLock.readLock();
    private Lock writeLock = rwLock.writeLock();
    //创建一个需要更新的数据
    private int num;

    public void update(int newData){
        writeLock.lock();//获取写锁
        try {
            num = newData;//更新数据
            System.out.println("数据更新为："+newData);
            //锁降级，先获取读锁，再释放写锁，读己之所写
            readLock.lock();//获取读锁
            System.out.println("锁降级");
        }finally {
            writeLock.unlock();//释放写锁
        }

        try {
            //在持有读锁的情况下执行其它操作，读己之所写
            int data =  read();
            System.out.println("更新后的数据为 = " + data);
        }finally {
            readLock.unlock();//释放读锁
        }
    }

    public int read(){
        readLock.lock();
        try {
            return num;
        }finally {
            readLock.unlock();
        }
    }


    public static void main(String[] args) {
        LockDowngradingDemo demo = new LockDowngradingDemo();
        new Thread(() ->{
            demo.update(45);
        }).start();
        new Thread(() ->{
            int read = demo.read();
            System.out.println("直接读取的数据为： " + read);
        }).start();
    }

}
